﻿/*
 * KRPCNetwork Handler
 * 
 * Author: snowdreamist
 * Date: 2011/11/24
 * 
 */

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Linq;
using System.Text;

namespace BitTorrentSharp.KRPC.Network
{
    public sealed class DefaultKRPCNetworkHandler : IKRPCNetworkHandler
    {
        internal DefaultKRPCNetworkHandler(int port)
        {
            this._udpClient = new UdpClient(port);
            this._udpClient.BeginReceive(this.UDPClientAsyncReceiveCallback, null);
        }

        #region protected
        /// <summary>
        /// When received data
        /// </summary>
        /// <param name="data"></param>
        protected void OnDataReceived(byte[] data, IPEndPoint remoteEndPoint)
        {
            if (data == null)
                throw new ArgumentNullException("data");
            if (this.DataReceived != null)
                this.DataReceived(this, new DataReceivedEventArgs(data, remoteEndPoint));
        }

        #endregion

        #region private
        /// <summary>
        /// UDP client
        /// </summary>
        private UdpClient _udpClient;
        /// <summary>
        /// Receive callback
        /// </summary>
        private void UDPClientAsyncReceiveCallback(IAsyncResult r)
        {
            IPEndPoint remoteEndPoint = null;
            byte[] data;
            // end receive
            try
            {
                data = this._udpClient.EndReceive(r, ref remoteEndPoint);
            }
            catch (Exception error)
            {
                // error
                throw;
            }

            // begin new receive
            this._udpClient.BeginReceive(this.UDPClientAsyncReceiveCallback, null);
            // process data
            this.OnDataReceived(data, remoteEndPoint);
        }
        #endregion

        #region events
        /// <summary>
        /// data received
        /// </summary>
        public event EventHandler<DataReceivedEventArgs> DataReceived;

        #endregion
    }
}
